/********************************************************************
	filename: 	Triangle2D.cpp
	created:	2010/04/20
	author:		Xiuwei Chen

	purpose:	Implement of class 2D Triangle

	All rights Reserved
*********************************************************************/

#include "Triangle2D.h"
#include "Trilinear.h"
#include "GeoAlgorithm2D.h"

/// <Summary>
/// Zero of 2D triangle
/// </Summary>
const Triangle2D Triangle2D::Zero = Triangle2D(0, 0, 0, 0, 0, 0);

/// <Summary>
/// default constructor
/// </Summary>
Triangle2D::Triangle2D()
	: p0(0, 0), p1(0, 0), p2(0, 0)
{
}

/// <Summary>
/// copy constructor
/// </Summary>
Triangle2D::Triangle2D(const Triangle2D &triangle)
	: p0(triangle.p0), p1(triangle.p1), p2(triangle.p2)
{
}

/// <Summary>
/// constructor
/// </Summary>
Triangle2D::Triangle2D(const Point2D &_p0, const Point2D &_p1, const Point2D &_p2)
	: p0(_p0), p1(_p1), p2(_p2)
{
}

/// <Summary>
/// constructor
/// </Summary>
Triangle2D::Triangle2D(Point2D *p)
	: p0(p[0]), p1(p[1]), p2(p[2])
{
}

/// <Summary>
/// constructor
/// </Summary>
Triangle2D::Triangle2D(double x0, double y0, double x1, double y1, double x2, double y2)
	: p0(x0, y0), p1(x1, y1), p2(x2, y2)
{
}

/// <Summary>
/// set value
/// </Summary>
void Triangle2D::SetValue(const Point2D &_p0, const Point2D &_p1, const Point2D &_p2)
{
	p0 = _p0;
	p1 = _p1;
	p2 = _p2;
}

/// <Summary>
/// set value
/// </Summary>
void Triangle2D::SetValue(Point2D *p)
{
	p0 = p[0];
	p1 = p[1];
	p2 = p[2];
}

/// <Summary>
/// set value
/// </Summary>
void Triangle2D::SetValue(double x0, double y0, double x1, double y1, double x2, double y2)
{
	p0.x = x0;
	p0.y = y0;
	p1.x = x1;
	p1.y = y1;
	p2.x = x2;
	p2.y = y2;
}

/// <Summary>
/// overload operation: assignment
/// </Summary>
Triangle2D & Triangle2D::operator = (const Triangle2D &t)
{
	p0 = t.p0;
	p1 = t.p1;
	p2 = t.p2;
	return *this;
}

/// <Summary>
/// overload operation: "=="
/// </Summary>
bool Triangle2D::operator == (const Triangle2D &t) const
{
	return p0 == t.p0 && p1 == t.p1 && p2 == t.p2;
}

/// <Summary>
/// overload operation: "!="
/// </Summary>
bool Triangle2D::operator != (const Triangle2D &t) const
{
	return p0 != t.p0 || p1 != t.p1 || p2 != t.p2;
}

/// <Summary>
/// Translation by 2D vector
/// </Summary>
void Triangle2D::Translation(const Vector2D &v)
{
	p0 += v;
	p1 += v;
	p2 += v;
}

/// <Summary>
/// rotate counter clockwise around a point (radian)
/// </Summary>
void Triangle2D::Rotation(const Point2D &center, double angle)
{
	p0.Rotation(center, angle);
	p1.Rotation(center, angle);
	p2.Rotation(center, angle);
}

/// <Summary>
/// Area of 2D Triangle
/// </Summary>
double Triangle2D::Area() const
{
	return fabs(p0.x * (p1.y - p2.y) + p1.x * (p2.y - p0.y) + p2.x * (p0.y - p1.y)) / 2;
}

/// <Summary>
/// Oriented area of 2D Triangle
/// </Summary>
double Triangle2D::AreaOriented() const
{
	return (p0.x * (p1.y - p2.y) + p1.x * (p2.y - p0.y) + p2.x * (p0.y - p1.y)) / 2;
}

/// <Summary>
/// center of excircle
/// </Summary>
Point2D Triangle2D::ExcircleCenter() const
{
	double d0 = DistanceSquare(p1, p2);
	double d1 = DistanceSquare(p2, p0);
	double d2 = DistanceSquare(p0, p1);
	double k0 = -d0 + d1 + d2;
	double k1 = -d1 + d2 + d0;
	double k2 = -d2 + d0 + d1;
	Point2D ret;
	Convert(Trilinear(d0 * k0, d1 * k1, d2 * k2), *this, ret);
	return ret;
}

/// <Summary>
/// center of incircle
/// </Summary>
Point2D Triangle2D::IncircleCenter() const
{
	Point2D ret;
	Convert(Trilinear(1, 1, 1), *this, ret);
	return ret;
}

/// <Summary>
/// radius of excircle
/// </Summary>
double Triangle2D::ExcircleRadius() const
{
	return Distance(p0, ExcircleCenter());
}

/// <Summary>
/// radius of incircle
/// </Summary>
double Triangle2D::IncircleRadius() const
{
	double d0 = Distance(p1, p2);
	double d1 = Distance(p2, p0);
	double d2 = Distance(p0, p1);
	return 2 * Area() / (d0 + d1 + d2);
}